using System;
using System.Collections;
using System.Linq;
using System.IO;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization;
#if WINDOWS
using System.Runtime.Serialization.Formatters.Binary;
#endif
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using GameStateManagement;

#if XBOX
using System.Xml;
using System.Xml.Serialization;
using Microsoft.Xna.Framework.Storage;
#endif

// ****************************************************************************** //
//        This component handles all the game state updates during gameplay       //
//           It can be considered as the core-gameplay system of the game         //
//                          together with the F# classes                          //
// ****************************************************************************** //

namespace Frogger_Game
{
    //inner class that handles the timers used by the game
    // and shared by different components
    public class GameTimer
    {
        //timer
       public float timer = 0;

       public const int TIME_LIMIT = 4;
    }

    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class GameLogic : Microsoft.Xna.Framework.GameComponent
    {
        //sound component
        SoundData sound;

        //a bool variable to know if the current level has been already checked
        bool checked_level;

        //two bool variables to know if the respective sound has been already started
        bool made_sound_win;
        bool made_sound_lost;

        GamePadState gpsPrev, gps;
        KeyboardState ksPrev, ks;

        GameTimer t = new GameTimer();

        //constructor
        public GameLogic(Game game)
            : base(game)
        {
            Game.Services.AddService(typeof(GameTimer), t);
        }


        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run. This is where it can query for any required services and load non- graphics content.
        /// </summary>
        public override void Initialize()
        {
            sound = (SoundData)Game.Services.GetService(typeof(SoundData));
            sound.SetMusicVolume(Game1.musicVolume);
            sound.SetEffectsVolume(Game1.effectsVolume);

            checked_level = false;
            made_sound_win = false;
            made_sound_lost = false;
            t.timer = 0;

            //Reset every previous game state
            FrogSimulation.reset_state();
            CarsTypes.reset_state();
            RiverTypes.reset_state();
            GameState.reset_state();
            WinLogic.check_level();

            //get keyboard and gamepad state
            ksPrev = Keyboard.GetState();
            gpsPrev = GamePad.GetState(PlayerIndex.One);

            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            gpsPrev = gps;
            ksPrev = ks;
            gps = GamePad.GetState(PlayerIndex.One);
            ks = Keyboard.GetState();

            //if game is not in pause
            if (Game1.isPaused == false) 
            { 
                var dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
                t.timer += dt;

                //we verify if the level-check is needed
                if (GameState.game_state.level != 1 && checked_level == false)
                {
                    checked_level = true;
                    WinLogic.check_level();
                }

                //update the whole game state
                CarsSimulation.update_state(dt);
                RiverSimulation.update_state(dt);
                GameLogicUpdate.update_script();
                WinLogic.update_win_check(dt);

                //if we are in wait-for-start mode, we reset the game state time counter
                if (t.timer < GameTimer.TIME_LIMIT && WinLogic.win_level == false && WinLogic.lost_level == false)
                {
                    Game1.isWaiting = true;
                    GameState.game_state.time_counter = 0;
                    sound.PlaySound(sound.StartSoundInstance);
                    made_sound_win = false;
                    made_sound_lost = false;

                }
                
                //we are finally ready to start the game, so to update frog and let it move
                if (t.timer > GameTimer.TIME_LIMIT && WinLogic.win_level == false && WinLogic.lost_level == false)
                {
                    FrogSimulation.update_script();
                    Game1.isWaiting = false;
                }

                //if the level has been completed, we need to restart the ready-to-start counter
                if (WinLogic.win_level == true && made_sound_win == false)
                {
                    t.timer = -GameTimer.TIME_LIMIT;
                    sound.PlaySound(sound.WinSoundInstance);
                    made_sound_win = true;
                }

                //if the level has been lost (frog died), we need to restart the ready-to-start counter
                if (WinLogic.lost_level == true && made_sound_lost == false)
                {
                    t.timer = -GameTimer.TIME_LIMIT;
                    sound.PlaySound(sound.GameOverSoundInstance);
                    made_sound_lost = true;
                }

                //if we want to pause the game we have to press Escape button on Keyboard
                // or Y button on GamePad
                if ((ks.IsKeyDown(Keys.Escape) && ksPrev.IsKeyUp(Keys.Escape)) || (gps.IsButtonDown(Buttons.Y) && gpsPrev.IsButtonUp(Buttons.Y)))
                {
                    Game1.isPaused = true;
                    Game.Services.RemoveService(typeof(InputState));
                    Game.Services.RemoveService(typeof(InputButtons));
                    sound.PauseAllEffects();
                    Game.Components.Add(new Input(Game));
                    Game.Components.Add(new Pause_Menu(Game));
                }

                Casanova.commit_variable_updates();
                    
                base.Update(gameTime);
            }
        }

        protected override void Dispose(bool disposing)
        {
            Game.Services.RemoveService(typeof(GameTimer));
            base.Dispose(disposing);
        }


    }
}
